﻿
using Moq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Xunit;
using Xunit.Extensions;

namespace EmperialApps.WeatherSpark.Data {

    public class TestForecast {

        [Fact]
        public void Ctor_GivenSparseData_ReturnsExpectedValues( ) {
            var start = DateTimeOffset.Now;
            var expected = new Forecast( default( Coordinate ), DD, start, 1, Dictionary(
                Pair.Create( ForecastData.Temperature, ReadOnly( 1, 2, 3 ) ),
                Pair.Create( ForecastData.SkyCover, ReadOnly( 0.1, 0.2, 0.3 ) ) ) );

            var actual = new Forecast( default( Coordinate ), DD, start, 1, Dictionary(
                Pair.Create( ForecastData.Temperature, ReadOnly( 1, 2, 3 ) ),
                Pair.Create( ForecastData.PrecipitationPotential, ReadOnly( ) ),
                Pair.Create( ForecastData.SkyCover, ReadOnly( 0.1, 0.2, 0.3 ) ),
                Pair.Create( ForecastData.RelativeHumidity, ReadOnly( ) ) ) );

            actual.AssertEqual( expected );
        }

        [Theory]
        [InlineData( 1 )]
        [InlineData( 2 )]
        [InlineData( 3 )]
        [InlineData( 6 )]
        public void Ctor_GivenSupportedInterval_ReturnsIntervalValue( int expected ) {
            var forecast = new Forecast( default( Coordinate ), DD, DateTimeOffset.Now, expected, ReadOnly( 1, 2, 3 ) );
            int actual = forecast.Interval;

            Assert.Equal( expected, actual );
        }

        [Theory]
        [InlineData( -1 )]
        [InlineData( 0 )]
        [InlineData( 4 )]
        [InlineData( 5 )]
        [InlineData( 7 )]
        public void Ctor_GivenUnsupportedInterval_ThrowsArgumentOutOfRangeException( int interval ) {
            var ex = Assert.Throws<ArgumentOutOfRangeException>( ( ) => new Forecast( default( Coordinate ), DD, DateTimeOffset.Now, interval, ReadOnly( 1, 2, 3 ) ) );

            Assert.Equal( ex.ParamName, "interval" );
        }


        [Fact]
        public void TryGetRedirectUri_OnForecastWithoutRedirect_ReturnsNull( ) {
            var start = DateTimeOffset.Now;
            var expected = Tuple.Create( false, default( string ) );
            var forecast = new Forecast( default( Coordinate ), DD, start, 1, Dictionary(
                Pair.Create( ForecastData.Temperature, ReadOnly( 1, 2, 3 ) ),
                Pair.Create( ForecastData.SkyCover, ReadOnly( 0.1, 0.2, 0.3 ) ) ) );

            string redirect;
            var actual = Tuple.Create( forecast.TryGetRedirectUri( out redirect ), redirect );

            Assert.Equal( actual, expected );
        }

        [Fact]
        public void TryGetRedirectUri_OnForecastWithRedirect_ReturnsValue( ) {
            var start = DateTimeOffset.Now;
            var expected = Tuple.Create( true, "REDIRECT" );
            var expectedForecast = new Forecast( default( Coordinate ), DD, start, 1, Dictionary(
                Pair.Create( ForecastData.Temperature, ReadOnly( 1, 2, 3 ) ),
                Pair.Create( ForecastData.SkyCover, ReadOnly( 0.1, 0.2, 0.3 ) ) ) );

            string redirect;
            var actualForecast = expectedForecast.Redirect( expected.Item2 );
            var actual = Tuple.Create( actualForecast.TryGetRedirectUri( out redirect ), redirect );

            Assert.Equal( actual, expected );

            // (verify all data members, other than Description)
            var forecastAssertions = typeof( Equal ).GetFields( )
                .Where( f => f.FieldType == typeof( IAssertion<Forecast> ) && f.Name != "Description" )
                .Select( f => (IAssertion<Forecast>)f.GetValue( null ) )
                .ToArray( );
            actualForecast.AssertAll( expectedForecast, forecastAssertions );
        }


        [Fact]
        public void Save_DoesNotCloseStream( ) {
            var streamMock = new Mock<Stream>( );
            streamMock.SetupGet( m => m.CanWrite ).Returns( true );
            var forecast = new Forecast( default( Coordinate ), DD, DateTimeOffset.Now, ReadOnly( 1, 2, 3, 4, 5 ) );

            streamMock.Setup( m => m.Close( ) ).Throws<Xunit.Sdk.AssertException>( );

            Assert.DoesNotThrow( ( ) => forecast.Save( streamMock.Object ) );
        }

        [Theory]
        [InlineData( 0 )]
        [InlineData( 1 )]
        [InlineData( 2 )]
        [InlineData( 3 )]
        [InlineData( 4 )]
        [InlineData( 5 )]
        public void Load_GivenValueFromSave_ReturnsOriginalValues( int state ) {
            Forecast expected;
            switch( state ) {
                default:
                case 0:
                    expected = new Forecast(
                        new Coordinate( 12.34, 56.78 ), DD,
                        new DateTimeOffset( 123456789123456789L, TimeSpan.FromHours( -2 ) ),
                        ReadOnly( -62.2, 56.7, -80, 134 ) );    // http://ggweather.com/climate/extremes_us.htm
                    break;
                case 1:
                    expected = new Forecast(
                        default( Coordinate ), DD,
                        new DateTimeOffset( 1111, 11, 11, 11, 0, 0, TimeSpan.FromHours( 1 ) ), 6,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly( 0, 1, 2, 4, 5, 6, 7, 8, 9 ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly( double.NaN, double.NaN, double.NaN, 9, 8, 7, 6, 5, 4 ) )
                        ) );
                    break;
                case 2:
                    expected = GetXmlFileData( XmlFile.dwml );
                    break;
                case 3:
                    expected = GetXmlFileData( XmlFile.yrnoEidal );
                    break;
                case 4:
                    expected = GetXmlFileData( XmlFile.yrnoTokyo );
                    break;
                case 5:
                    expected = LoadXmlFile( XmlFile.dwmlNoCloudCover, DefaultFallbackLocation );
                    break;
            }

            using( var stream = new MemoryStream( ) ) {
                expected.Save( stream );
                stream.Position = 0;

                var actual = Forecast.Load( stream );

                actual.AssertEqual( expected );
            }
        }

        [Theory]
        [InlineData( XmlFile.dwml )]
        [InlineData( XmlFile.dwmlPreTransition )]
        [InlineData( XmlFile.dwmlPostTransition )]
        [InlineData( XmlFile.dwmlContainingNil )]
        [InlineData( XmlFile.dwmlReordered )]
        [InlineData( XmlFile.dwmlNoCloudCover )]
        [InlineData( XmlFile.yrnoEidal )]
        [InlineData( XmlFile.yrnoLondon )]
        [InlineData( XmlFile.yrnoMontevideo )]
        [InlineData( XmlFile.yrnoRome )]
        [InlineData( XmlFile.yrnoSydney )]
        [InlineData( XmlFile.yrnoTiverton )]
        [InlineData( XmlFile.yrnoTokyo )]
        [InlineData( XmlFile.yrnoPositiveOffset )]
        [InlineData( XmlFile.yrnoNegativeOffset )]
        public void Load_GivenValidXml_LoadsExpectedValues( XmlFile file ) {
            var expected = GetXmlFileData( file );

            Forecast actual = LoadXmlFile( file, DefaultFallbackLocation );

            actual.AssertEqual( expected );
        }

        [Theory]
        [InlineData( XmlFile.dwml )]
        [InlineData( XmlFile.dwmlPreTransition )]
        [InlineData( XmlFile.dwmlPostTransition )]
        [InlineData( XmlFile.dwmlContainingNil )]
        [InlineData( XmlFile.dwmlReordered )]
        [InlineData( XmlFile.dwmlNoCloudCover )]
        [InlineData( XmlFile.yrnoEidal )]
        [InlineData( XmlFile.yrnoLondon )]
        [InlineData( XmlFile.yrnoMontevideo )]
        [InlineData( XmlFile.yrnoRome )]
        [InlineData( XmlFile.yrnoSydney )]
        [InlineData( XmlFile.yrnoTiverton )]
        [InlineData( XmlFile.yrnoTokyo )]
        [InlineData( XmlFile.yrnoPositiveOffset )]
        [InlineData( XmlFile.yrnoNegativeOffset )]
        public void Load_GivenValidXml_UnderDifferentCulture_LoadsExpectedValues( XmlFile file ) {
            CultureInfo currentCulture = CultureInfo.CurrentCulture;
            Forecast expected = GetXmlFileData( file );

            Forecast actual;
            try {
                Thread.CurrentThread.CurrentCulture = new CultureInfo( "ru" );
                actual = LoadXmlFile( file, DefaultFallbackLocation );
            }
            finally {
                Thread.CurrentThread.CurrentCulture = currentCulture;
            }

            actual.AssertEqual( expected );
        }

        [Theory]
        [InlineData( XmlFile.dwml )]
        [InlineData( XmlFile.dwmlPreTransition )]
        [InlineData( XmlFile.dwmlPostTransition )]
        [InlineData( XmlFile.dwmlContainingNil )]
        [InlineData( XmlFile.dwmlReordered )]
        [InlineData( XmlFile.dwmlNoCloudCover )]
        [InlineData( XmlFile.yrnoEidal )]
        [InlineData( XmlFile.yrnoLondon )]
        [InlineData( XmlFile.yrnoMontevideo )]
        [InlineData( XmlFile.yrnoRome )]
        [InlineData( XmlFile.yrnoSydney )]
        [InlineData( XmlFile.yrnoTiverton )]
        [InlineData( XmlFile.yrnoTokyo )]
        [InlineData( XmlFile.yrnoPositiveOffset )]
        [InlineData( XmlFile.yrnoNegativeOffset )]
        public void Load_GivenValidXml_ReturnsDataWithSameIntervalAsForecast( XmlFile file ) {
            Forecast forecast = LoadXmlFile( file, DefaultFallbackLocation );
            var expected = Enumerable.Repeat( forecast.Interval, 7 ).ToArray( );

            var actual = typeof( Forecast ).GetProperties( )
                .Where( p => p.PropertyType == typeof( DataValues ) )
                .Select( p => ((DataValues)p.GetValue( forecast, null )).Interval )
                .ToArray( );

            Assert.Equal( expected, actual );
        }

        [Theory]
        [InlineData( XmlFile.dwmlNoTemperature )]
        public void Load_GivenInvalidXml_ThrowsFormatException( XmlFile file ) {
            var ex = Assert.Throws<FormatException>( ( ) => LoadXmlFile( file ) );

            Assert.Contains( "temperature data", ex.Message );
        }

        [Fact]
        public void Load_GivenXmlWithInvalidLocation_UsesFallbackLocation( ) {
            Coordinate expected = new Coordinate( 12.34, -56.78 );

            Forecast forecast = LoadXmlFile( XmlFile.dwmlNoLocation, expected );

            Assert.Equal( expected, forecast.Location );
        }

        [Fact]
        public void Load_GivenInvalidStream_ThrowsFormatException( ) {
            Stream source = new MemoryStream( Encoding.UTF8.GetBytes( "<invalid/>" ) );

            var ex = Assert.Throws<FormatException>( ( ) => Forecast.Load( source ) );
        }


        [Theory]
        [InlineData( 5 )]
        [InlineData( 10 )]
        public void Trim_GivenSufficientCount_ReturnsExistingForecast( int maximumHours ) {
            var forecast = new Forecast( default( Coordinate ), DD, DateTimeOffset.Now, ReadOnly( 1, 2, 3, 4, 5 ) );

            var actual = Forecast.Trim( forecast, maximumHours );

            Assert.Same( forecast, actual );
        }

        [Theory]
        [InlineData( true )]
        [InlineData( false )]
        public void Trim_GivenCountLessThanForecast_ReturnsTrimmedForecast( bool oneHourInterval ) {
            var start = DateTimeOffset.Now;
            int interval = oneHourInterval ? 1 : 2;
            var expected = new Forecast( default( Coordinate ), DD, start, interval, oneHourInterval ? ReadOnly( 1, 2, 3, 4, 5, 6 ) : ReadOnly( 1, 2, 3 ) );
            var forecast = new Forecast( default( Coordinate ), DD, start, interval, ReadOnly( 1, 2, 3, 4, 5, 6, 7, 8, 9 ) );

            var actual = Forecast.Trim( forecast, 6 );

            actual.AssertEqual( expected );
        }


        [Theory]
        [InlineData( true )]
        [InlineData( false )]
        public void Combine_GivenDisjointData_ReturnsLaterForecast( bool earlierFirst ) {
            var earlier = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 11, 0, 0, TimeSpan.FromHours( 1 ) ),
                ReadOnly( 0, 1, 2, 3, 4 ) );
            var later = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 22, 11, 0, 0, TimeSpan.FromHours( 1 ) ),
                ReadOnly( 5, 6, 7, 8, 9 ) );
            var first = earlierFirst ? earlier : later;
            var second = earlierFirst ? later : earlier;

            var actual = Forecast.Combine( first, second );

            Assert.Same( later, actual );
        }

        [Fact]
        public void Combine_GivenSameStartAndDifferentData_ReturnsLargerForecast( ) {
            var first = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 11, 0, 0, TimeSpan.FromHours( 1 ) ),
                ReadOnly( 4, 5, 6, 7, 8, 9 ) );
            var second = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 11, 0, 0, TimeSpan.FromHours( 1 ) ),
                ReadOnly( 0, 1, 2, 3 ) );

            var actual = Forecast.Combine( first, second );

            Assert.Same( first, actual );
        }

        [Fact]
        public void Combine_GivenSparseForecastsWithNearbyData_ReturnsCombinedPaddedData( ) {
            var expected = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 11, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, ReadOnly( 0, 1, 2, 4, 5, 6, 7, 8, 9 ) ),
                    Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly( double.NaN, double.NaN, double.NaN, 9, 8, 7, 6, 5, 4 ) )
                ) );
            var first = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 14, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, ReadOnly( 4, 5, 6, 7, 8, 9 ) ),
                    Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly( 9, 8, 7, 6, 5, 4 ) )
                ) );
            var second = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 11, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, ReadOnly( 0, 1, 2, 3 ) )
                ) );

            var actual = Forecast.Combine( first, second );

            actual.AssertEqual( expected );
        }

        [Theory]
        [InlineData( 0, 2, 3, 0, new double[] { 0, 1, 3, 4, 5, 6, 7, 8, 9 } )]
        [InlineData( 1, 2, 3, 3, new double[] { 1, 2, 4, 5, 6, 7, 8, 9 } )]
        [InlineData( 0, 3, 2, 0, new double[] { 0, 0, 1, 2, 2, 3, 5, 6, 7, 8, 9 } )]
        [InlineData( 1, 3, 2, 2, new double[] { 0, 1, 1, 2, 3, 5, 6, 7, 8, 9 } )]
        [InlineData( 2, 3, 2, 2, new double[] { 0, 0, 1, 2, 2, 5, 6, 7, 8, 9 } )]
        [InlineData( 0, 3, 6, 0, new double[] { 0, 2, 5, 6, 7, 8, 9 } )]
        [InlineData( 1, 3, 6, 6, new double[] { 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 2, 3, 6, 6, new double[] { 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 3, 3, 6, 6, new double[] { 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 4, 3, 6, 6, new double[] { 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 5, 3, 6, 6, new double[] { 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 6, 3, 6, 6, new double[] { 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 7, 3, 6, 12, new double[] { 5, 6, 7, 8, 9 } )]
        [InlineData( 0, 6, 3, 0, new double[] { 0, 0, 1, 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 1, 6, 3, 3, new double[] { 0, 0, 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 2, 6, 3, 3, new double[] { 0, 0, 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 3, 6, 3, 3, new double[] { 0, 0, 1, 5, 6, 7, 8, 9 } )]
        [InlineData( 4, 6, 3, 6, new double[] { 0, 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 5, 6, 3, 6, new double[] { 0, 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 6, 6, 3, 6, new double[] { 0, 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 7, 6, 3, 9, new double[] { 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 8, 6, 3, 9, new double[] { 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 9, 6, 3, 9, new double[] { 0, 5, 6, 7, 8, 9 } )]
        [InlineData( 10, 6, 3, 12, new double[] { 5, 6, 7, 8, 9 } )]
        public void Combine_GivenForecastsWithDifferentIntervals_ReturnsCombinedResampledData( int firstHour, int firstInterval, int secondInterval, int expectedHour, double[] expectedData ) {
            var expected = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, expectedHour, 0, 0, TimeSpan.FromHours( 1 ) ), secondInterval,
                ReadOnly( expectedData ) );
            var first = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, firstHour, 0, 0, TimeSpan.FromHours( 1 ) ), firstInterval,
                ReadOnly( 0, 1, 2, 3, 4, 5, 6, 7, 8 ) );
            var second = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 12, 0, 0, TimeSpan.FromHours( 1 ) ), secondInterval,
                ReadOnly( 5, 6, 7, 8, 9 ) );

            var actual = Forecast.Combine( first, second );

            actual.AssertEqual( expected );
        }

        [Theory]
        // Interval: 1
        [InlineData( 1, 1, 0, 6, 24, 6, new double[] { 5, 6, 7, 8, 9 } )]  // gap
        [InlineData( 1, 1, 0, 0, 24, 0, new double[] { 5, 6, 7, 8, 9 } )]  // same
        [InlineData( 1, 1, 0, 5, 24, 0, new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } )]  // consecutive
        [InlineData( 1, 1, 2, 5, 24, 2, new double[] { 0, 1, 2, 5, 6, 7, 8, 9 } )]  // first overlapping
        [InlineData( 1, 1, 5, 3, 24, 3, new double[] { 5, 6, 0, 1, 2, 3, 4 } )]  // second overlapping
        [InlineData( 1, 1, 2, 4, 6, 3, new double[] { 1, 5, 6, 7, 8, 9 } )]  // reduce combined size
        [InlineData( 1, 1, 0, 2, 4, 3, new double[] { 6, 7, 8, 9 } )]  // reduce initial size
        // Interval: 2
        [InlineData( 1, 2, 0, 12, 24, 12, new double[] { 5, 6, 7, 8, 9 } )]  // gap
        [InlineData( 1, 2, 0, 0, 24, 0, new double[] { 5, 6, 7, 8, 9 } )]  // same
        [InlineData( 1, 2, 0, 10, 24, 0, new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } )]  // consecutive
        [InlineData( 1, 2, 4, 10, 24, 4, new double[] { 0, 1, 2, 5, 6, 7, 8, 9 } )]  // first overlapping
        [InlineData( 1, 2, 10, 6, 24, 6, new double[] { 5, 6, 0, 1, 2, 3, 4 } )]  // second overlapping
        [InlineData( 1, 2, 4, 8, 12, 6, new double[] { 1, 5, 6, 7, 8, 9 } )]  // reduce combined size
        [InlineData( 1, 2, 0, 4, 8, 6, new double[] { 6, 7, 8, 9 } )]  // reduce initial size
        // Interval: 6
        [InlineData( -9, 6, 0, 0, 30, 0, new double[] { 5, 6, 7, 8, 9 } )]  // same
        [InlineData( -9, 6, 0, 12, 99, 0, new double[] { 0, 1, 5, 6, 7, 8, 9 } )]  // first overlapping
        [InlineData( -9, 6, 18, 6, 48, 6, new double[] { 5, 6, 0, 1, 2, 3, 4 } )]  // second overlapping
        [InlineData( -9, 6, 6, 18, 36, 12, new double[] { 1, 5, 6, 7, 8, 9 } )]  // reduce combined size
        [InlineData( -9, 6, 0, 6, 24, 12, new double[] { 6, 7, 8, 9 } )]  // reduce initial size
        public void Combine_GivenNearbyData_ReturnsDataWithinLimit(
            int offset, int interval, int firstHour, int secondHour, int maximumHours,
            int expectedHour, double[] expectedData ) {
            Assert.True( firstHour % interval == 0, "First hour " + firstHour + " not a multiple of interval " + interval );
            Assert.True( secondHour % interval == 0, "second hour " + secondHour + " not a multiple of interval " + interval );
            Assert.True( expectedHour % interval == 0, "expected hour " + expectedHour + " not a multiple of interval " + interval );

            var expected = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, expectedHour, 0, 0, TimeSpan.FromHours( offset ) ), interval,
                Dictionary( expectedData ) );

            var first = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, firstHour, 0, 0, TimeSpan.FromHours( offset ) ), interval,
                Dictionary( 0, 1, 2, 3, 4 ) );
            var second = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, secondHour, 0, 0, TimeSpan.FromHours( offset ) ), interval,
                Dictionary( 5, 6, 7, 8, 9 ) );

            var actual = Forecast.Combine( first, second, maximumHours );

            actual.AssertEqual( expected );
        }

        [Fact]
        public void Combine_GivenDataCrossingDaylightSaving_UsesLaterOffset( ) {
            Forecast first = LoadXmlFile( XmlFile.dwmlPreTransition );
            Forecast second = LoadXmlFile( XmlFile.dwmlPostTransition );
            var expected = new Forecast(
                second.Location,
                second.Description,
                second.Start.AddHours( -36 ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, ReadOnly( first.Temperature.Skip( 37 ).Take( 36 ).Concat( second.Temperature ).ToArray( ) ) ),
                    Pair.Create( ForecastData.PrecipitationPotential, ReadOnly( first.PrecipitationPotential.Skip( 37 ).Take( 36 ).Concat( second.PrecipitationPotential ).ToArray( ) ) ),
                    Pair.Create( ForecastData.SkyCover, ReadOnly( first.SkyCover.Skip( 37 ).Take( 36 ).Concat( second.SkyCover ).ToArray( ) ) ),
                    Pair.Create( ForecastData.RelativeHumidity, ReadOnly( first.RelativeHumidity.Skip( 37 ).Take( 36 ).Concat( second.RelativeHumidity ).ToArray( ) ) ),
                    Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly( first.WindSpeed.Skip( 37 ).Take( 36 ).Concat( second.WindSpeed ).ToArray( ) ) ),
                    Pair.Create( ForecastData.WindDirection, ReadOnly( first.WindDirection.Skip( 37 ).Take( 36 ).Concat( second.WindDirection ).ToArray( ) ) )
                ) );

            var actual = Forecast.Combine( first, second, expected.Temperature.Count );

            actual.AssertEqual( expected );
        }

        [Fact]
        public void Combine_GivenForecastsContainingMultipleNilValues_DoesNotThrow( ) {
            Forecast first = LoadFile( XmlFile.dwmlContainingNil + ".bin" );
            Forecast second = LoadXmlFile( XmlFile.dwmlContainingNil );
            var expected = Tuple.Create(
                1 + second.Temperature.Count,
                1 + second.PrecipitationPotential.Count,
                1 + second.SkyCover.Count,
                1 + second.RelativeHumidity.Count );

            var result = Forecast.Combine( first, second );
            var actual = Tuple.Create(
                result.Temperature.Count,
                result.PrecipitationPotential.Count,
                result.SkyCover.Count,
                result.RelativeHumidity.Count );

            Assert.Equal( expected, actual );
        }

        [Fact]
        public void Combine_GivenForecastsContainingUnusedFillerValues_DoesNotThrow( ) {
            Forecast forecast = LoadXmlFile( XmlFile.dwml );
            Forecast fillerForecast = new Forecast(
                forecast.Location, forecast.Description, forecast.Start.GetDateOffset( ), 1,
                Enumerable.Range( 0, (int)Math.Log( (int)ForecastData.Last, 2 ) + 1 ).ToDictionary(
                  i => (ForecastData)(int)Math.Pow( 2, i ),
                  i => FillerData ) );
            int difference = forecast.Start.Hour;
            var expected = Tuple.Create(
                difference + forecast.Temperature.Count,
                difference + forecast.PrecipitationPotential.Count,
                difference + forecast.SkyCover.Count,
                difference + forecast.RelativeHumidity.Count );

            var result = Forecast.Combine( fillerForecast, forecast );
            var actual = Tuple.Create(
                result.Temperature.Count,
                result.PrecipitationPotential.Count,
                result.SkyCover.Count,
                result.RelativeHumidity.Count );

            Assert.Equal( expected, actual );
        }

        [Fact]
        public void Combine_GivenForecastsWithMismatchedData_DoesNotThrow( ) {
            int hour = 14;
            var data = ReadOnly( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 );
            var expected = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 0, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, ReadOnly( Enumerable.Repeat( double.NaN, hour ).Concat( data ).ToArray( ) ) ),
                    Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly( FillerData.Take( 2 ).Concat( FillerData ).ToArray( ) ) )
                ) );
            var first = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 0, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, FillerData ),
                    Pair.Create( ForecastData.WindSustainedSpeed, FillerData )
                ) );
            var second = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, hour, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, data )
                ) );

            var actual = Forecast.Combine( first, second );

            actual.AssertEqual( expected );
        }

        [Fact]
        public void Combine_GivenForecastsWithYrnoOnlyData_DoesNotThrow( ) {
            int hour = 1;
            var data = ReadOnly( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 );
            var expected = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 0, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, data ),
                    Pair.Create( ForecastData.Pressure, ReadOnly( FillerData.Take( hour ).Concat( data.Skip( hour ) ).ToArray( ) ) )
                ) );
            var first = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, 0, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, data )
                ) );
            var second = new Forecast(
                default( Coordinate ), DD,
                new DateTimeOffset( 1111, 11, 11, hour, 0, 0, TimeSpan.FromHours( 1 ) ), 1,
                Dictionary(
                    Pair.Create( ForecastData.Temperature, ReadOnly( data.Skip( hour ).ToArray( ) ) ),
                    Pair.Create( ForecastData.Pressure, ReadOnly( data.Skip( hour ).ToArray( ) ) )
                ) );

            var actual = Forecast.Combine( first, second );

            actual.AssertEqual( expected );
        }


        #region Utility

        private const string DD = "Default Description";

        private static readonly ReadOnlyCollection<double> FillerData = ReadOnly( Enumerable.Repeat( double.NaN, 24 ).ToArray( ) );
        private static readonly Coordinate DefaultFallbackLocation = new Coordinate( 12.34, -56.78 );

        private static Forecast[] _xmlFileData = new Forecast[Enum.GetValues( typeof( XmlFile ) ).Length];
        private static Forecast GetXmlFileData( XmlFile file ) {
            int index = (int)file;
            if( _xmlFileData[index] == null ) {
                _xmlFileData[index] =
                    file == XmlFile.dwml ? new Forecast(
                        new Coordinate( 30.27, -97.74 ), "Austin TX",
                        new DateTimeOffset( 2012, 02, 19, 7, 0, 0, 0, TimeSpan.FromHours( -6 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                5.6, 6.1, 8.3, 10.6, 12.8, 14.4, 16.1, 17.2, 18.3, 17.8, 17.8, 16.7, 15, 13.3, 12.2, 11.1, 10, 9.4, 8.9, 8.3, 7.8, 7.2, 7.2, 6.7,
                                7.2, 8.3, 10, 12.2, 14.4, 16.7, 17.8, 18.9, 20, 20, 19.4, 18.3, 16.7, 15, 13.3, 12.8, 11.7, 10.6, 10, 9.4, 9.4, 8.9, 8.3, 8.3,
                                8.9, 10, 11.7, 14.4, 17.2, 19.4, 21.1, 22.2, 23.3, 23.3, 22.8, 21.7, 20, 18.3, 16.7, 16.1, 15, 14.4, 13.3, 13.3, 12.8, 12.2, 11.7, 11.7,
                                12.2, 12.8, 14.4, 16.7, 18.9, 21.1, 22.2, 23.3, 23.9, 23.9, 23.3, 22.2, 20, 17.8, 16.1, 14.4, 13.3, 12.2, 11.7, 11.1, 10.6, 9.4, 9.4, 8.9,
                                9.4, 11.1, 13.3, 16.7, 18.9, 21.7, 23.3, 25, 26.1, 26.1, 25.6, 24.4, 21.7, 19.4, 17.2, 15.6, 14.4, 13.3, 12.2, 11.7, 11.1, 10, 10, 9.4,
                                9.4, 10.6, 11.7, 13.3, 14.4, 15.6, 16.7, 17.2, 17.8, 17.8, 17.2, 16.7, 14.4, 12.8, 11.1, 10, 8.9, 7.8, 7.2, 6.7, 6.1, 5.6, 5.6, 5,
                                5.6, 6.7, 8.3, 10.6, 12.8, 15, 16.1, 17.2, 18.3, 18.3, 17.8, 17.2, 15.6, 13.9, 12.2, 11.7, 10.6, 10, 8.9, 8.9, 8.3, 7.8, 7.8, 7.2
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
                                0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.05,
                                0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05,
                                0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
                                0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
                                0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                0.71, 0.71, 0.52, 0.52, 0.52, 0.23, 0.23, 0.23, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.34, 0.34, 0.34, 0.8, 0.8, 0.8, 0.9, 0.9, 0.9, 0.9,
                                0.9, 0.9, 0.9, 0.9, 0.9, 0.83, 0.83, 0.83, 0.73, 0.73, 0.73, 0.63, 0.63, 0.63, 0.57, 0.57, 0.57, 0.5, 0.5, 0.5, 0.39, 0.39, 0.39, 0.29,
                                0.29, 0.29, 0.31, 0.31, 0.31, 0.41, 0.41, 0.41, 0.49, 0.49, 0.49, 0.76, 0.76, 0.76, 0.8, 0.8, 0.8, 0.82, 0.82, 0.82, 0.82, 0.82, 0.82, 0.81,
                                0.81, 0.81, 0.7, 0.49, 0.27, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3,
                                0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4,
                                0.4, 0.4, 0.4, 0.4, 0.4, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.74, 0.74, 0.74, 0.9, 0.9, 0.9, 0.95
                            ) ),
                            Pair.Create( ForecastData.RelativeHumidity, ReadOnly(
                                1.0, 0.99, 0.88, 0.74, 0.65, 0.56, 0.52, 0.49, 0.47, 0.48, 0.51, 0.54, 0.61, 0.69, 0.77, 0.81, 0.86, 0.91, 0.93, 0.94, 0.95, 0.98, 0.99, 1.0,
                                1.0, 1.0, 0.91, 0.81, 0.76, 0.69, 0.64, 0.61, 0.58, 0.58, 0.59, 0.61, 0.68, 0.74, 0.82, 0.86, 0.89, 0.94, 0.92, 0.85, 0.82, 0.81, 0.75, 0.73,
                                0.73, 0.72, 0.65, 0.53, 0.45, 0.38, 0.36, 0.37, 0.36, 0.36, 0.37, 0.38, 0.43, 0.49, 0.54, 0.6, 0.7, 0.76, 0.8, 0.84, 0.88, 0.91, 0.94, 0.98,
                                0.93, 0.84, 0.73, 0.61, 0.52, 0.45, 0.41, 0.36, 0.32, 0.3, 0.29, 0.3, 0.35, 0.4, 0.45, 0.49, 0.52, 0.56, 0.59, 0.6, 0.62, 0.63, 0.64, 0.65,
                                0.64, 0.61, 0.55, 0.47, 0.41, 0.36, 0.32, 0.31, 0.29, 0.3, 0.32, 0.35, 0.41, 0.48, 0.56, 0.61, 0.67, 0.73, 0.75, 0.73, 0.71, 0.7, 0.67, 0.67,
                                0.65, 0.61, 0.55, 0.48, 0.44, 0.39, 0.37, 0.36, 0.34, 0.34, 0.35, 0.37, 0.43, 0.47, 0.53, 0.56, 0.59, 0.63, 0.66, 0.68, 0.7, 0.71, 0.72, 0.74,
                                0.72, 0.68, 0.61, 0.52, 0.46, 0.41, 0.38, 0.36, 0.34, 0.35, 0.37, 0.39, 0.44, 0.5, 0.56, 0.62, 0.67, 0.72, 0.76, 0.8, 0.84, 0.88, 0.91, 0.94
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                3.1, 3.1, 3.1, 2.7, 2.2, 2.2, 2.2, 2.2, 2.2, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 3.1, 3.6, 3.6, 3.6, 3.1, 3.1,
                                3.1, 3.6, 4.0, 4.5, 4.9, 5.8, 6.3, 6.3, 6.3, 5.8, 4.9, 4.0, 3.6, 3.1, 2.7, 2.7, 2.7, 2.2, 2.2, 2.2, 1.3, 1.3, 1.3, 1.3,
                                2.2, 2.7, 2.7, 2.7, 2.2, 2.2, 2.2, 2.7, 3.1, 3.1, 3.6, 3.6, 3.6, 3.1, 3.1, 3.1, 3.6, 3.6, 3.6, 3.6, 3.6, 3.6, 3.6, 3.1,
                                3.6, 4.0, 4.5, 4.5, 4.9, 4.9, 5.8, 5.8, 5.8, 4.5, 4.0, 3.1, 3.1, 2.7, 2.7, 2.7, 2.7, 2.7, 3.1, 3.1, 3.1, 3.1, 3.6, 3.6,
                                4.0, 4.9, 5.8, 5.8, 6.3, 6.3, 6.3, 6.3, 6.3, 4.9, 4.0, 3.1, 2.7, 2.7, 2.2, 2.2, 2.2, 2.2, 2.7, 3.1, 3.6, 4.0, 4.9, 6.3,
                                6.3, 6.7, 7.2, 7.6, 7.6, 7.6, 7.6, 7.2, 6.7, 6.3, 5.8, 4.9, 4.5, 4.5, 4.0, 3.6, 3.6, 3.1, 2.7, 2.7, 2.2, 2.2, 2.2, 1.3,
                                2.2, 2.7, 3.1, 3.6, 4.0, 4.0, 4.5, 4.5, 4.5, 4.0, 4.0, 3.6, 3.6, 3.6, 3.6, 3.1, 3.1, 3.1, 3.1, 2.7, 2.7, 2.7, 2.7, 2.7
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                350, 0, 0, 10, 30, 40, 60, 90, 110, 120, 130, 130, 130, 130, 130, 140, 150, 150, 160, 170, 170, 170, 160, 160,
                                160, 150, 150, 160, 180, 190, 190, 200, 200, 200, 200, 200, 200, 200, 200, 210, 240, 250, 260, 290, 310, 310, 330, 340,
                                350, 10, 20, 30, 60, 70, 90, 120, 140, 150, 160, 160, 160, 170, 170, 180, 190, 190, 190, 200, 200, 200, 220, 220,
                                230, 240, 250, 260, 270, 270, 270, 280, 280, 280, 280, 280, 280, 270, 260, 260, 250, 240, 240, 240, 240, 240, 230, 230,
                                230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 240, 270, 290, 320, 340, 350, 350, 0, 0, 10, 10, 10,
                                10, 20, 20, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 40, 40, 50, 50, 60, 60,
                                60, 70, 80, 90, 100, 110, 110, 110, 110, 110, 120, 120, 120, 120, 130, 130, 130, 130, 130, 140, 140, 140, 140, 140
                            ) )
                        )
                    ) :
                    file == XmlFile.dwmlPreTransition ? new Forecast(
                        new Coordinate( 30.27, -97.74 ), "Austin TX",
                        new DateTimeOffset( 2012, 03, 08, 19, 0, 0, 0, TimeSpan.FromHours( -6 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                14.4, 13.9, 12.8, 12.2, 11.7, 11.1, 10, 9.4, 8.3, 7.8, 7.2, 6.7, 7.2, 7.2, 7.2, 7.8, 8.3, 8.3, 8.9, 8.9, 8.9, 8.9, 8.9, 8.9,
                                8.3, 8.3, 7.8, 7.8, 7.8, 7.8, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.8, 8.3, 8.9, 9.4, 10.6, 10.6, 11.1, 11.1, 11.1, 11.1, 11.1,
                                11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.7, 12.8, 13.9, 15, 16.1, 16.7, 17.2, 17.8, 17.8, 17.8, 17.2,
                                16.7, 15.6, 15, 14.4, 14.4, 13.9, 13.3, 13.3, 13.3, 12.8, 12.8, 12.8, 13.3, 14.4, 16.1, 18.3, 20, 21.7, 23.3, 24.4, 25, 25, 25, 24.4,
                                23.3, 22.2, 21.1, 20.6, 20, 19.4, 18.9, 18.3, 18.3, 17.8, 17.8, 17.2, 17.8, 18.3, 20, 21.1, 22.2, 23.3, 23.9, 25, 25.6, 25.6, 25, 25,
                                23.9, 22.8, 22.2, 21.7, 21.1, 20.6, 20.6, 20, 20, 19.4, 19.4, 19.4, 19.4, 20, 21.1, 22.2, 22.8, 23.9, 24.4, 25, 25, 25, 25, 24.4,
                                23.3, 22.8, 21.7, 21.1, 20.6, 20, 19.4, 19.4, 18.9, 18.9, 18.3, 18.3, 18.3, 19.4, 20.6, 21.7, 22.2, 23.3, 23.9, 24.4, 25, 25, 25, 24.4
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7,
                                0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.8,
                                0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
                                1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.99,
                                0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.58,
                                0.58, 0.58, 0.58, 0.58, 0.58, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.68, 0.68, 0.68, 0.68, 0.68, 0.68, 0.44, 0.44, 0.44, 0.44, 0.44, 0.44, 0.42,
                                0.42, 0.42, 0.42, 0.42, 0.42, 0.91, 0.91, 0.91, 0.91, 0.91, 0.91, 0.92, 0.92, 0.92, 0.92, 0.92, 0.92, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.68,
                                0.68, 0.68, 0.68, 0.68, 0.68, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75,
                                0.75, 0.75, 0.75, 0.75, 0.75, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.65
                            ) ),
                            Pair.Create( ForecastData.RelativeHumidity, ReadOnly(
                                0.8, 0.78, 0.76, 0.74, 0.72, 0.71, 0.76, 0.79, 0.81, 0.84, 0.85, 0.88, 0.87, 0.86, 0.84, 0.82, 0.8, 0.78, 0.77, 0.76, 0.75, 0.75, 0.76, 0.76,
                                0.78, 0.8, 0.82, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.89, 0.9, 0.91, 0.9, 0.88, 0.85, 0.81, 0.78, 0.76, 0.75, 0.74, 0.74, 0.76, 0.78, 0.78,
                                0.81, 0.85, 0.9, 0.94, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.95, 0.89, 0.83, 0.78, 0.75, 0.73, 0.71, 0.71, 0.72, 0.73,
                                0.77, 0.79, 0.82, 0.83, 0.84, 0.85, 0.87, 0.88, 0.89, 0.89, 0.9, 0.91, 0.9, 0.88, 0.82, 0.77, 0.72, 0.67, 0.62, 0.59, 0.57, 0.58, 0.6, 0.62,
                                0.67, 0.72, 0.77, 0.81, 0.85, 0.88, 0.91, 0.94, 0.97, 0.99, 1.0, 1.0, 1.0, 0.97, 0.91, 0.85, 0.8, 0.75, 0.71, 0.68, 0.66, 0.66, 0.66, 0.67,
                                0.71, 0.75, 0.79, 0.81, 0.84, 0.86, 0.88, 0.9, 0.91, 0.92, 0.93, 0.94, 0.93, 0.9, 0.87, 0.82, 0.79, 0.75, 0.72, 0.7, 0.67, 0.66, 0.67, 0.68,
                                0.72, 0.76, 0.79, 0.82, 0.84, 0.86, 0.89, 0.91, 0.92, 0.94, 0.95, 0.96, 0.94, 0.89, 0.83, 0.77, 0.72, 0.68, 0.65, 0.63, 0.62, 0.62, 0.63, 0.65
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                10.7, 11.2, 11.2, 10.7, 10.3, 9.8, 9.8, 9.8, 9.4, 9.4, 8.9, 8.9, 8.0, 8.0, 8.0, 8.0, 7.6, 7.6, 7.2, 7.2, 6.7, 6.3, 6.3, 5.8,
                                5.8, 4.9, 4.9, 4.5, 4.5, 4.5, 4.0, 4.0, 4.0, 3.6, 3.6, 3.6, 3.1, 3.1, 3.1, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7,
                                2.7, 2.7, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 1.3, 1.3, 1.3, 1.3, 1.3, 2.2, 2.7, 3.1, 3.6, 4.0, 4.0,
                                4.0, 3.6, 3.1, 3.1, 2.7, 2.2, 2.2, 1.3, 1.3, 1.3, 1.3, 1.3, 2.2, 2.2, 2.7, 3.1, 3.1, 3.6, 3.6, 4.0, 4.0, 4.0, 4.0, 4.0,
                                4.0, 4.0, 4.0, 3.6, 3.6, 3.6, 3.1, 3.1, 2.7, 2.2, 2.2, 2.2, 2.7, 2.7, 3.1, 3.6, 4.0, 4.0, 4.5, 4.5, 4.5, 4.0, 4.0, 4.0,
                                4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 3.6, 3.6, 3.1, 3.1, 3.1, 3.1, 3.6, 3.6, 4.0, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.0,
                                4.0, 4.0, 4.0, 3.6, 3.6, 3.6, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1, 3.6, 3.6, 3.6, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                0, 0, 0, 0, 0, 0, 0, 0, 350, 350, 350, 350, 350, 0, 0, 10, 10, 10, 10, 10, 10, 20, 20, 20,
                                20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 30, 30, 30,
                                40, 60, 90, 110, 130, 140, 160, 180, 200, 220, 250, 260, 260, 260, 270, 270, 270, 270, 270, 250, 230, 220, 200, 190,
                                190, 190, 190, 190, 180, 180, 190, 190, 200, 200, 210, 210, 210, 200, 200, 190, 180, 180, 180, 170, 170, 160, 160, 160,
                                160, 160, 160, 160, 160, 160, 160, 160, 160, 150, 150, 150, 150, 150, 150, 150, 160, 160, 160, 150, 150, 150, 150, 150,
                                150, 150, 150, 150, 150, 150, 150, 150, 150, 140, 140, 140, 140, 140, 150, 150, 150, 150, 150, 150, 140, 140, 140, 130,
                                140, 140, 140, 150, 150, 150, 150, 150, 150, 150, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 130, 130, 130
                            ) )
                        )
                    ) :
                    file == XmlFile.dwmlPostTransition ? new Forecast(
                        new Coordinate( 30.27, -97.74 ), "Austin TX",
                        new DateTimeOffset( 2012, 03, 11, 21, 0, 0, 0, TimeSpan.FromHours( -5 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                16.1, 14.4, 13.3, 12.8, 11.7, 11.1, 10.6, 10, 10, 9.4, 8.9, 10, 11.7, 14.4, 17.2, 20, 22.8, 24.4, 26.1, 27.2, 27.2, 27.2, 26.1, 24.4,
                                22.8, 21.7, 20.6, 19.4, 18.9, 18.3, 17.8, 17.2, 16.7, 16.7, 16.1, 16.7, 17.2, 18.9, 20, 21.7, 22.8, 23.9, 24.4, 25, 25, 25, 24.4, 23.3,
                                22.2, 21.1, 20.6, 19.4, 18.9, 18.9, 18.3, 17.8, 17.8, 17.8, 17.2, 17.8, 18.3, 19.4, 20.6, 21.7, 22.8, 23.3, 23.9, 24.4, 24.4, 24.4, 23.9, 22.8,
                                21.7, 20.6, 20, 19.4, 18.9, 18.3, 18.3, 17.8, 17.8, 17.8, 17.2, 17.8, 18.3, 20, 21.1, 22.2, 23.3, 24.4, 25, 25.6, 25.6, 25.6, 25, 23.3,
                                22.8, 21.7, 20.6, 20, 19.4, 18.9, 18.9, 18.3, 18.3, 17.8, 17.8, 18.3, 18.9, 20, 21.1, 22.2, 23.3, 23.9, 24.4, 25, 25, 25, 24.4, 23.3,
                                22.2, 21.7, 21.1, 20.6, 20, 19.4, 19.4, 18.9, 18.9, 18.3, 18.3, 18.9, 19.4, 20.6, 21.7, 22.8, 23.9, 25, 25.6, 26.1, 26.1, 25.6, 25, 23.9,
                                22.8, 22.2, 21.7, 20.6, 20.6, 20, 19.4, 19.4, 18.9, 18.9, 18.3, 18.9, 19.4, 20.6, 21.7, 22.8, 23.9, 24.4, 25, 25.6, 25.6, 25.6, 25, 25
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05, 0.05,
                                0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2,
                                0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2,
                                0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3,
                                0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.2, 0.2,
                                0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2,
                                0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.1, 0.1
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                0.1, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.3, 0.3, 0.3, 0.1, 0.1, 0.1, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3,
                                0.3, 0.5, 0.5, 0.5, 0.7, 0.7, 0.7, 0.8, 0.8, 0.8, 0.9, 0.9, 0.9, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.6, 0.6, 0.6, 0.6, 0.6,
                                0.6, 0.6, 0.6, 0.6, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.7, 0.7, 0.7, 0.6, 0.6, 0.6, 0.7, 0.7,
                                0.7, 0.8, 0.8, 0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.8, 0.8, 0.8, 0.6, 0.6, 0.6, 0.7, 0.7,
                                0.7, 0.8, 0.8, 0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7, 0.7,
                                0.7, 0.7, 0.7, 0.7, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7,
                                0.7, 0.7, 0.7, 0.7, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.4, 0.4
                            ) ),
                            Pair.Create( ForecastData.RelativeHumidity, ReadOnly(
                                0.84, 0.91, 0.96, 0.97, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.98, 0.84, 0.73, 0.67, 0.6, 0.55, 0.52, 0.5, 0.51, 0.54, 0.58, 0.65,
                                0.73, 0.8, 0.84, 0.86, 0.89, 0.93, 0.94, 0.96, 0.98, 1.0, 1.0, 1.0, 0.97, 0.9, 0.84, 0.81, 0.77, 0.73, 0.71, 0.7, 0.69, 0.7, 0.72, 0.76,
                                0.78, 0.82, 0.86, 0.89, 0.92, 0.94, 0.94, 0.95, 0.97, 0.99, 1.0, 0.99, 0.95, 0.89, 0.84, 0.8, 0.77, 0.73, 0.68, 0.65, 0.66, 0.68, 0.7, 0.75,
                                0.8, 0.84, 0.88, 0.91, 0.94, 0.97, 0.98, 0.99, 1.0, 1.0, 1.0, 0.99, 0.94, 0.86, 0.79, 0.73, 0.68, 0.65, 0.62, 0.6, 0.6, 0.61, 0.62, 0.67,
                                0.72, 0.77, 0.81, 0.84, 0.88, 0.9, 0.92, 0.94, 0.95, 0.96, 0.98, 0.96, 0.9, 0.83, 0.77, 0.71, 0.67, 0.64, 0.62, 0.6, 0.6, 0.61, 0.63, 0.67,
                                0.72, 0.77, 0.81, 0.85, 0.88, 0.91, 0.93, 0.94, 0.96, 0.98, 0.99, 0.97, 0.91, 0.84, 0.78, 0.72, 0.67, 0.64, 0.62, 0.6, 0.6, 0.61, 0.63, 0.67,
                                0.72, 0.76, 0.8, 0.83, 0.86, 0.89, 0.93, 0.96, 0.99, 1.0, 1.0, 1.0, 0.96, 0.9, 0.83, 0.78, 0.73, 0.7, 0.67, 0.64, 0.64, 0.65, 0.66, 0.67
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                2.2, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.9, 0.4, 0.4, 0.0, 0.0, 0.4, 0.9, 2.2, 2.7, 3.6, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 3.6,
                                3.1, 3.1, 2.7, 2.7, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 1.3, 2.2, 2.2, 2.7, 3.1, 4.0, 4.5, 4.5, 4.5, 4.5, 4.5, 4.9, 5.8, 5.8,
                                4.9, 4.9, 4.5, 4.0, 3.6, 3.6, 3.1, 3.1, 2.7, 2.7, 2.7, 3.1, 3.6, 3.6, 4.0, 4.5, 4.9, 4.5, 4.5, 4.0, 4.0, 3.6, 3.1, 3.1,
                                3.1, 3.1, 3.1, 3.6, 3.6, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1, 3.6, 4.0, 4.5, 4.9, 5.8, 5.8, 5.8, 4.9, 4.5, 4.0, 3.6, 3.1, 3.1,
                                3.1, 3.1, 3.6, 3.6, 3.6, 3.6, 3.6, 3.1, 3.1, 3.1, 3.1, 3.6, 4.0, 4.5, 4.9, 5.8, 6.3, 6.3, 5.8, 4.9, 4.9, 4.5, 4.5, 4.5,
                                4.5, 4.9, 5.8, 5.8, 6.3, 6.3, 5.8, 5.8, 5.8, 4.9, 4.9, 5.8, 5.8, 6.3, 6.7, 6.7, 6.7, 6.7, 6.3, 5.8, 4.9, 4.5, 4.0, 4.0,
                                4.0, 4.0, 4.0, 4.5, 4.5, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.5, 4.5, 4.9, 4.9, 5.8, 5.8, 4.9, 4.9, 4.5, 4.5, 4.0, 4.0
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                160, 160, 160, 170, 170, 170, 170, 170, 190, 210, 220, 210, 190, 180, 180, 180, 180, 180, 170, 170, 170, 160, 150, 150,
                                140, 140, 140, 150, 150, 150, 140, 140, 130, 120, 110, 110, 110, 110, 120, 130, 140, 140, 150, 150, 140, 140, 130, 140,
                                140, 140, 150, 150, 150, 150, 150, 140, 140, 140, 140, 140, 140, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
                                150, 160, 160, 160, 160, 160, 160, 150, 150, 150, 140, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
                                150, 150, 150, 160, 160, 160, 150, 150, 150, 150, 150, 150, 150, 150, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
                                160, 160, 160, 160, 160, 160, 160, 160, 160, 150, 150, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 150, 160,
                                160, 160, 160, 160, 170, 170, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 150, 150, 150, 150
                            ) )
                        )
                    ) :
                    file == XmlFile.dwmlContainingNil ? new Forecast(
                        new Coordinate( 42.60, -92.96 ), "Austinville IA",
                        new DateTimeOffset( 2012, 09, 10, 19, 0, 0, 0, TimeSpan.FromHours( -5 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                23.9, 21.1, 19.4, 18.3, 17.2, 16.7, 16.1, 15.6, 15.0, 14.4, 13.9, 13.9, 13.3, 15.6, 19.4, 23.3, 26.1, 28.3, 30.0, 31.1, 31.7, 32.2, 31.7, 30.6,
                                28.3, 25.0, 22.8, 21.7, 20.6, 20.0, 18.9, 18.3, 17.8, 17.8, 17.2, 16.7, 16.1, 17.8, 20.6, 23.3, 25.0, 26.7, 27.8, 28.9, 28.9, 29.4, 28.9, 27.8,
                                25.6, 22.2, 20.0, 18.9, 17.8, 17.2, 16.1, 15.6, 15.0, 15.0, 14.4, 13.9, 13.3, 13.9, 15.0, 16.1, 17.2, 17.8, 18.3, 18.3, 18.9, 18.9, 18.3, 17.8,
                                16.7, 14.4, 13.3, 12.8, 12.2, 11.7, 11.1, 10.6, 10.6, 10.6, 10.0, 9.4, 9.4, 10.6, 12.8, 15.0, 17.2, 18.3, 19.4, 20.0, 20.0, 20.6, 20.0, 19.4,
                                17.8, 15.0, 13.9, 12.8, 12.2, 11.7, 11.1, 10.6, 10.0, 10.0, 9.4, 9.4, 8.9, 10.6, 12.8, 15.6, 17.8, 19.4, 20.6, 21.7, 21.7, 22.2, 21.7, 21.1,
                                19.4, 16.7, 15.0, 14.4, 13.3, 12.8, 12.2, 11.7, 11.1, 11.1, 10.6, 10.6, 10.0, 11.7, 14.4, 17.2, 19.4, 21.1, 22.2, 23.3, 23.3, 23.9, 23.3, 22.8,
                                20.6, 17.8, 16.7, 15.6, 14.4, 13.9, 13.3, 12.8, 12.2, 12.2, 11.7, 11.7, 11.1, 12.2, 15.0, 17.2, 18.9, 20.6, 21.7, 22.2, 22.2, 22.8, 22.2, 21.1
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
                                0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11,
                                0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.81, 0.81, 0.81, 0.81, 0.81, 0.81, 0.69, 0.69, 0.69, 0.69, 0.69, 0.69, 0.43, 0.43, 0.43, 0.43, 0.43, 0.43,
                                0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.19,
                                0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09,
                                0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
                                0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06,
                                0.06, 0.06, 0.08, 0.10, 0.12, 0.15, 0.17, 0.17, 0.18, 0.19, 0.20, 0.22, 0.23, 0.25, 0.30, 0.35, 0.39, 0.44, 0.46, 0.49, 0.55, 0.61, 0.67, 0.72,
                                0.75, 0.77, 0.80, 0.83, 0.86, 0.89, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.96, 0.95, 0.94, 0.93, 0.91, 0.91, 0.89, 0.85, 0.81, 0.77, 0.73,
                                0.71, 0.69, 0.64, 0.60, 0.56, 0.51, 0.49, 0.48, 0.47, 0.46, 0.44, 0.43, 0.42, 0.42, 0.42, 0.42, 0.42, 0.42, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45,
                                0.36, 0.36, 0.36, 0.36, 0.36, 0.36, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.26, 0.26, 0.26, 0.26, 0.26, 0.26, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24,
                                0.19, 0.19, 0.19, 0.19, 0.19, 0.19, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13,
                                0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35
                            ) ),
                            Pair.Create( ForecastData.RelativeHumidity, ReadOnly(
                                0.41, 0.51, 0.59, 0.65, 0.70, 0.70, 0.72, 0.75, 0.78, 0.80, 0.83, 0.80, 0.83, 0.72, 0.56, 0.44, 0.38, 0.32, 0.29, 0.26, 0.24, 0.23, 0.24, 0.27,
                                0.32, 0.42, 0.51, 0.59, 0.63, 0.68, 0.73, 0.75, 0.75, 0.75, 0.75, 0.78, 0.78, 0.73, 0.61, 0.53, 0.48, 0.42, 0.40, 0.37, 0.36, 0.35, 0.36, 0.40,
                                0.45, 0.55, 0.63, 0.68, 0.73, 0.75, 0.81, 0.84, 0.87, 0.87, 0.86, 0.90, 0.93, 0.90, 0.83, 0.81, 0.75, 0.73, 0.70, 0.70, 0.65, 0.65, 0.68, 0.67,
                                0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.89, 0.89, 0.89, 0.89, 0.89, 0.89, 0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45,
                                0.52, 0.52, 0.52, 0.52, 0.52, 0.52, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.80, 0.80, 0.80, 0.80, 0.80, 0.80, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45,
                                0.52, 0.52, 0.52, 0.52, 0.52, 0.52, 0.77, 0.77, 0.77, 0.77, 0.77, 0.77, 0.86, 0.86, 0.86, 0.86, 0.86, 0.86, 0.44, 0.44, 0.44, 0.44, 0.44, 0.44,
                                0.53, 0.53, 0.53, 0.53, 0.53, 0.53, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 0.49, 0.49, 0.49, 0.49, 0.49, 0.49
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                5.8, 4.9, 4.9, 4.9, 4.9, 4.9, 4.9, 4.9, 5.8, 5.8, 5.8, 5.8, 5.8, 6.7, 7.6, 8.9, 9.8, 10.3, 10.7, 11.2, 11.2, 11.2, 10.7, 9.8,
                                8.9, 7.6, 6.7, 6.3, 6.3, 6.3, 6.3, 5.8, 4.5, 4.0, 3.6, 3.1, 2.7, 2.2, 0.9, 0.4, 0.4, 0.4, 0.4, 0.9, 1.3, 2.2, 2.2, 1.3,
                                1.3, 2.7, 3.6, 4.5, 4.9, 4.5, 4.5, 4.5, 4.0, 4.0, 4.0, 4.5, 4.5, 4.5, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 3.6, 3.6, 3.1,
                                3.1, 3.1, 2.7, 2.7, 2.7, 2.2, 2.2, 2.2, 2.2, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1,
                                2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3,
                                0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 3.1, 3.1, 3.1, 3.1, 3.1, 3.1,
                                2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 3.6, 3.6, 3.6, 3.6, 3.6, 3.6, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 2.7, 2.7, 2.7, 2.7, 2.7, 2.7
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 190, 190, 190, 190, 190, 190, 200, 200, 200, 200, 200, 200, 200,
                                200, 190, 190, 190, 190, 200, 200, 200, 200, 200, 210, 210, 220, 190, 130, 100, 130, 190, 220, 220, 220, 220, 270, 350,
                                30, 30, 30, 20, 30, 30, 30, 30, 20, 20, 20, 30, 30, 30, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
                                20, 20, 20, 20, 20, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                350, 350, 350, 350, 350, 350, 340, 340, 340, 340, 340, 340, 320, 320, 320, 320, 320, 320, 260, 260, 260, 260, 260, 260,
                                200, 200, 200, 200, 200, 200, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 200, 200, 200, 200, 200, 200,
                                170, 170, 170, 170, 170, 170, 180, 180, 180, 180, 180, 180, 200, 200, 200, 200, 200, 200, 240, 240, 240, 240, 240, 240
                            ) )
                        )
                    ) :
                    file == XmlFile.dwmlReordered ? new Forecast(
                        new Coordinate( 36.01, -82.99 ), "5 Miles E Parrottsville TN",
                        new DateTimeOffset( 2014, 03, 13, 20, 0, 0, 0, TimeSpan.FromHours( -4 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                                                                                                                                   2.8, 1.7, 1.1, 0.6,
                                0.6, 0.0, -0.6, -0.6, -1.1, -1.1, -1.7, -1.7, -1.1, 0.6, 3.3, 6.1, 8.3, 10.6, 12.2, 13.3, 13.9, 15.0, 14.4, 13.3, 12.2, 11.1, 10.0, 8.9,
                                8.3, 7.8, 7.2, 6.7, 6.1, 5.6, 5.6, 5.0, 4.4, 5.6, 7.8, 9.4, 11.1, 12.2, 13.3, 13.9, 14.4, 15.0, 14.4, 13.9, 12.8, 11.7, 10.6, 10.0,
                                9.4, 8.9, 8.3, 7.8, 7.8, 7.2, 6.7, 6.1, 6.1, 6.7, 7.8, 8.9, 9.4, 10.6, 11.1, 11.7, 11.7, 11.7, 11.1, 10.6, 8.9, 7.8, 6.7, 6.1,
                                5.6, 5.0, 4.4, 3.9, 3.3, 2.8, 2.2, 2.2, 1.7, 2.2, 3.9, 5.0, 6.1, 7.2, 7.8, 8.3, 8.9, 8.9, 8.3, 7.8, 6.7, 5.6, 4.4, 3.9,
                                3.3, 2.8, 2.2, 1.7, 1.7, 1.1, 0.6, 0.0, 0.0, 2.2, 4.4, 6.7, 8.9, 11.1, 12.8, 13.9, 14.4, 15.0, 14.4, 13.3, 12.2, 10.6, 9.4, 8.9,
                                8.3, 7.2, 6.7, 6.1, 5.6, 5.6, 5.0, 4.4, 3.9, 5.6, 7.8, 9.4, 11.1, 12.8, 14.4, 15.0, 15.6, 16.1, 15.6, 14.4, 12.8, 11.1, 10.0, 8.9,
                                8.3, 7.8, 6.7, 6.1, 5.6, 5.0, 4.4, 3.9, 3.3, 4.4, 6.7, 8.3, 10.0, 11.1, 12.2, 12.8, 13.3, 13.9, 13.3, 12.2
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                                                                                                                    0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.23, 0.23, 0.23, 0.23, 0.23, 0.23, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.35, 0.35, 0.35, 0.35,
                                0.35, 0.35, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.6, 0.6, 0.6, 0.6,
                                0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.36, 0.36, 0.36, 0.36, 0.36, 0.36, 0.26, 0.26, 0.26, 0.26, 0.26, 0.26, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.1, 0.1, 0.1, 0.1,
                                0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.2, 0.2, 0.2, 0.2,
                                0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                                                                                                                                0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.65, 0.65, 0.65, 0.7,
                                0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75,
                                0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95,
                                0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.62, 0.62, 0.62, 0.62,
                                0.62, 0.62, 0.44, 0.44, 0.44, 0.44, 0.44, 0.44, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.4, 0.4, 0.4, 0.4,
                                0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
                                0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5
                            ) ),
                            Pair.Create( ForecastData.RelativeHumidity, ReadOnly(
                                                                                                                                                      0.29, 0.35, 0.38, 0.43,
                                0.45, 0.47, 0.51, 0.53, 0.55, 0.58, 0.63, 0.66, 0.63, 0.58, 0.48, 0.41, 0.35, 0.3, 0.27, 0.26, 0.27, 0.26, 0.28, 0.3, 0.36, 0.41, 0.44, 0.49,
                                0.51, 0.55, 0.58, 0.6, 0.62, 0.65, 0.65, 0.67, 0.73, 0.73, 0.65, 0.63, 0.59, 0.57, 0.53, 0.51, 0.51, 0.49, 0.53, 0.55, 0.61, 0.66, 0.74, 0.77,
                                0.8, 0.86, 0.89, 0.93, 0.93, 0.96, 1.0, 1.0, 1.0, 0.96, 0.89, 0.83, 0.8, 0.77, 0.74, 0.71, 0.71, 0.71, 0.74, 0.77, 0.83, 0.86, 0.89, 0.89,
                                0.89, 0.92, 0.92, 0.96, 0.96, 1.0, 1.0, 1.0, 1.0, 1.0, 0.85, 0.79, 0.73, 0.65, 0.63, 0.6, 0.56, 0.56, 0.58, 0.58, 0.62, 0.67, 0.73, 0.76,
                                0.76, 0.79, 0.79, 0.82, 0.85, 0.89, 0.92, 0.92, 0.92, 0.82, 0.73, 0.65, 0.58, 0.5, 0.45, 0.42, 0.39, 0.37, 0.39, 0.43, 0.48, 0.56, 0.61, 0.65,
                                0.71, 0.76, 0.79, 0.82, 0.82, 0.82, 0.85, 0.85, 0.89, 0.79, 0.71, 0.66, 0.61, 0.57, 0.53, 0.51, 0.49, 0.46, 0.47, 0.49, 0.53, 0.59, 0.63, 0.68,
                                0.68, 0.71, 0.76, 0.79, 0.79, 0.82, 0.82, 0.82, 0.85, 0.79, 0.68, 0.58, 0.52, 0.48, 0.45, 0.43, 0.42, 0.4, 0.42, 0.43
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                                                                                                                    2.7, 2.2, 2.2, 2.2,
                                2.2, 2.2, 2.2, 1.3, 1.3, 1.3, 1.3, 1.3, 2.2, 2.2, 2.7, 3.1, 4.0, 4.5, 4.9, 4.9, 4.5, 4.5, 4.0, 3.6, 3.6, 2.7, 2.2, 1.3,
                                1.3, 1.3, 1.3, 0.9, 0.4, 0.0, 0.0, 0.0, 0.4, 0.4, 0.9, 1.3, 2.7, 3.1, 3.6, 3.6, 3.1, 2.7, 2.7, 2.7, 2.7, 2.2, 2.2, 1.3,
                                0.9, 0.9, 0.9, 0.9, 1.3, 1.3, 1.3, 0.9, 0.9, 1.3, 2.7, 3.1, 3.1, 3.1, 3.1, 3.1, 2.7, 2.7, 2.7, 3.1, 3.1, 3.1, 2.7, 2.7,
                                2.7, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.7, 2.7, 2.7, 3.1, 3.1, 3.1, 3.6, 3.6, 3.6, 3.1, 3.1, 3.1, 3.1, 3.1, 3.6, 4.0, 4.0,
                                3.6, 3.1, 2.7, 3.1, 3.1, 3.6, 3.1, 2.7, 2.2, 1.3, 1.3, 1.3, 2.7, 3.6, 4.5, 4.5, 4.0, 3.6, 3.6, 3.6, 3.6, 3.1, 2.2, 1.3,
                                1.3, 1.3, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.7, 3.6, 4.9, 6.3, 6.3, 5.8, 4.9, 4.9, 5.8, 5.8, 4.5, 3.6, 2.7,
                                2.7, 3.1, 3.1, 3.1, 2.7, 2.2, 1.3, 0.9, 0.9, 2.2, 3.1, 4.5, 5.8, 7.2, 7.6, 8.0, 8.0, 7.6, 7.2, 6.7
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                                                                                                                    260, 240, 200, 180,
                                170, 160, 150, 150, 150, 140, 140, 140, 140, 160, 190, 210, 220, 240, 250, 250, 250, 250, 240, 230, 200, 200, 180, 170,
                                190, 210, 220, 210, 180, 170, 170, 180, 180, 220, 290, 330, 320, 290, 280, 260, 220, 200, 210, 230, 240, 220, 180, 160,
                                140, 100, 80, 100, 140, 150, 160, 180, 190, 180, 150, 140, 140, 130, 130, 130, 140, 150, 160, 190, 200, 230, 300, 340,
                                330, 310, 300, 310, 320, 320, 320, 310, 300, 320, 350, 0, 0, 0, 350, 0, 0, 0, 350, 340, 330, 320, 310, 310,
                                310, 310, 310, 320, 330, 330, 330, 310, 310, 320, 350, 0, 350, 320, 310, 280, 230, 200, 200, 190, 190, 190, 190, 190,
                                190, 190, 190, 190, 190, 200, 200, 200, 200, 200, 200, 210, 210, 230, 230, 250, 270, 280, 280, 290, 290, 300, 310, 310,
                                310, 310, 320, 320, 320, 320, 310, 270, 250, 260, 280, 290, 290, 290, 290, 290, 290, 300, 290, 290
                            ) )
                        )
                    ) :
                    file == XmlFile.dwmlNoCloudCover ? new Forecast(
                        DefaultFallbackLocation, "West Fargo ND",
                        new DateTimeOffset( 2015, 05, 30, 8, 0, 0, 0, TimeSpan.FromHours( -5 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                                                          3.3, 5.0, 7.2, 8.9, 11.1, 13.3, 13.9, 15.0, 15.6, 16.1, 16.1, 15.6, 14.4, 12.8, 11.1, 9.4, 8.3,
                                 7.2, 6.1, 5.0, 4.4, 5.0, 5.6, 7.2, 9.4, 11.7, 13.3, 14.4, 15.0, 15.0, 15.6, 16.7, 17.2, 17.2, 17.2, 16.1, 15.0, 13.3, 12.2, 11.1, 11.1,
                                10.6, 10.6, 10.0, 10.0, 10.0, 10.6, 11.1, 12.2, 13.9, 15.6, 16.7, 18.3, 19.4, 20.0, 20.6, 21.1, 21.7, 22.2, 21.7, 20.6, 18.9, 17.2, 16.7, 16.7,
                                16.1, 16.1, 15.0, 14.4, 14.4, 15.0, 15.0, 16.1, 17.2, 18.3, 20.0, 21.7, 22.8, 23.3, 23.9, 23.9, 23.3, 22.8, 22.2, 21.7, 21.1, 20.0, 19.4, 18.9,
                                18.3, 17.2, 16.7, 16.1, 16.1, 16.1, 16.1, 17.2, 17.8, 18.9, 20.0, 21.1, 22.2, 23.3, 23.9, 24.4, 24.4, 24.4, 23.9, 22.8, 21.7, 20.6, 18.9, 17.8,
                                16.7, 15.6, 15.0, 15.0, 15.0, 15.0, 15.0, 17.2, 18.3, 19.4, 20.6, 21.7, 22.8, 23.9, 24.4, 24.4, 24.4, 23.9, 23.3, 22.8, 21.7, 20.6, 19.4, 18.3,
                                17.2, 16.1, 15.6, 15.0, 15.0, 15.0, 15.0, 16.7, 17.8, 19.4, 20.6, 22.2, 23.3, 24.4, 25.0, 25.0, 25.0, 24.4, 23.9, 22.8, 21.7, 20.0, 18.3, 17.2,
                                16.1, 15.0, 14.4, 13.9, 13.9, 13.9, 13.9
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                                                        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                                                                                                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN,
                                double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN
                            ) ),
                            Pair.Create( ForecastData.RelativeHumidity, ReadOnly(
                                                                          0.70, 0.62, 0.56, 0.51, 0.46, 0.38, 0.37, 0.34, 0.33, 0.32, 0.33, 0.37, 0.40, 0.43, 0.48, 0.53, 0.56,
                                0.59, 0.64, 0.71, 0.76, 0.73, 0.70, 0.62, 0.54, 0.47, 0.43, 0.41, 0.41, 0.42, 0.41, 0.39, 0.38, 0.39, 0.40, 0.44, 0.48, 0.55, 0.60, 0.66, 0.67,
                                0.71, 0.71, 0.74, 0.75, 0.75, 0.73, 0.71, 0.68, 0.63, 0.58, 0.55, 0.50, 0.47, 0.46, 0.44, 0.42, 0.41, 0.39, 0.41, 0.44, 0.49, 0.56, 0.59, 0.63,
                                0.65, 0.67, 0.69, 0.72, 0.75, 0.79, 0.78, 0.78, 0.75, 0.75, 0.70, 0.66, 0.64, 0.64, 0.62, 0.64, 0.66, 0.68, 0.71, 0.73, 0.76, 0.81, 0.81, 0.84,
                                0.87, 0.93, 0.93, 0.97, 0.97, 0.97, 0.97, 0.93, 0.90, 0.87, 0.84, 0.81, 0.76, 0.71, 0.69, 0.66, 0.64, 0.64, 0.64, 0.66, 0.71, 0.73, 0.78, 0.81,
                                0.87, 0.93, 0.96, 0.96, 0.96, 0.96, 0.96, 0.84, 0.81, 0.75, 0.70, 0.68, 0.64, 0.60, 0.58, 0.58, 0.58, 0.58, 0.59, 0.62, 0.63, 0.68, 0.73, 0.75,
                                0.81, 0.87, 0.87, 0.90, 0.90, 0.90, 0.90, 0.81, 0.78, 0.70, 0.68, 0.64, 0.59, 0.56, 0.56, 0.56, 0.56, 0.58, 0.60, 0.64, 0.66, 0.70, 0.75, 0.81,
                                0.84, 0.87, 0.90, 0.93, 0.90, 0.90, 0.90
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                                                   5.8, 6.7, 6.3, 4.9, 4.5, 4.5, 4.5, 4.0, 4.0, 3.6, 4.0, 3.6, 3.1, 3.1, 2.7, 2.7, 2.2,
                                2.2, 2.2, 2.2, 2.7, 3.1, 3.6, 4.0, 4.5, 4.9, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 4.9, 4.9, 4.5, 4.0, 4.0, 4.0,
                                4.0, 4.0, 4.5, 4.9, 4.9, 5.8, 6.3, 6.7, 7.2, 7.6, 8.0, 8.9, 8.9, 8.9, 8.9, 8.0, 8.0, 7.6, 7.2, 7.2, 6.7, 6.3, 6.3, 5.8,
                                5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 6.3, 5.8, 5.8,
                                5.8, 5.8, 4.9, 4.9, 4.9, 4.5, 4.5, 4.5, 4.5, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 3.6, 3.6, 3.6, 3.6, 3.1, 3.1, 2.7, 2.7,
                                2.7, 2.7, 2.7, 3.1, 3.1, 3.6, 3.6, 3.6, 4.0, 4.0, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.0, 4.0, 3.6, 3.6, 3.1, 3.1, 2.7,
                                2.7, 2.7, 2.7, 3.1, 3.1, 3.6, 3.6, 3.6, 3.6, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 3.6, 3.6, 3.6, 3.1,
                                3.1, 3.1, 3.1, 3.1, 3.1, 3.6, 3.6
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                                            10, 20, 20, 20, 20, 20, 20, 20, 30, 40, 40, 50, 60, 60, 60, 70, 70,
                                80, 90, 110, 120, 120, 130, 140, 140, 140, 150, 150, 150, 150, 150, 150, 150, 150, 140, 140, 140, 140, 140, 140, 140,
                                130, 140, 140, 140, 140, 140, 140, 140, 140, 150, 150, 150, 150, 150, 150, 160, 160, 160, 170, 160, 160, 160, 160, 160,
                                160, 160, 160, 160, 160, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 140, 140, 140, 140, 140, 140, 150, 150, 160,
                                160, 160, 170, 170, 170, 180, 180, 190, 200, 220, 230, 240, 250, 240, 210, 180, 150, 120, 100, 100, 90, 80, 80, 70,
                                60, 60, 50, 30, 20, 10, 0, 10, 10, 20, 20, 30, 30, 30, 30, 40, 40, 40, 50, 50, 40, 40, 40, 40,
                                40, 40, 40, 40, 40, 30, 30, 40, 40, 50, 60, 60, 70, 70, 60, 60, 60, 60, 60, 60, 70, 80, 90, 100,
                                100, 100, 100, 100, 100, 90, 90
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoEidal ? new Forecast(
                        new Coordinate( 60.08, 9.52 ), "Eidal, Norway|http://www.yr.no/place/Norway/Buskerud/Sigdal/Eidal~83524/",
                        new DateTimeOffset( 2013, 07, 20, 18, 0, 0, 0, TimeSpan.FromMinutes( 120 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                                                                                        29, 28, 27, 25, 23, 21,
                                19, 19, 18, 17, 17, 16, 16, 18, 20, 21, 23, 24, 25, 25, 26, 26, 27, 27, 27, 26, 25, 24, 22, 20,
                                19, 18, 17, 16, 16, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                                                                                                          0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                                                                                                          0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                                                                                                          3.5, 3.5, 3.2, 2.8, 2.6, 2.5,
                                2.4, 2.4, 2.3, 2.2, 2.0, 1.9, 1.6, 0.9, 0.7, 1.3, 1.4, 1.7, 2.2, 2.8, 3.1, 3.2, 3.3, 3.1, 2.9, 2.7, 2.6, 2.1, 2.0, 1.5,
                                0.3, 2.5, 2.7, 2.2, 2.0, 1.9, 2.1, 2.1, 2.2, 2.0, 1.8, 1.7, 1.7, 1.7, 1.8, 2.0, 2.4, 2.6
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                                                                                                      320, 320, 310, 310, 310, 310,
                                310, 310, 310, 310, 300, 300, 310, 330, 40, 50, 70, 90, 120, 120, 120, 120, 110, 110, 110, 100, 120, 130, 130, 150,
                                130, 40, 40, 40, 30, 20, 30, 40, 50, 70, 90, 100, 110, 120, 120, 120, 110, 120
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                                                                                                                                                1016.9, 1016.8, 1017.1, 1017.4, 1017.7, 1018.1,
                                1018.5, 1018.7, 1018.9, 1019.0, 1019.0, 1019.0, 1019.4, 1019.8, 1020.0, 1020.0, 1019.9, 1019.7, 1019.4, 1018.7, 1017.9, 1017.2, 1016.4, 1015.8, 1015.9, 1016.1, 1016.5, 1016.9, 1017.5, 1018.0,
                                1018.8, 1019.2, 1019.8, 1020.3, 1020.8, 1021.2, 1021.6, 1021.8, 1021.8, 1021.6, 1021.4, 1021.3, 1021.0, 1020.6, 1020.4, 1020.0, 1019.7, 1019.0
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoLondon ? new Forecast(
                        new Coordinate( 51.51, -0.13 ), "London, United Kingdom|http://www.yr.no/place/United_Kingdom/England/London~2643743/",
                        new DateTimeOffset( 2013, 07, 20, 17, 0, 0, 0, TimeSpan.FromMinutes( 60 ) ), 1,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                                                                                    24, 24, 23, 21, 19, 18, 17,
                                17, 17, 17, 17, 17, 17, 17, 18, 18, 19, 21, 22, 24, 25, 26, 26, 27, 27, 26, 26, 25, 23, 22, 21,
                                20, 19, 19, 19, 19, 19, 19, 19, 20, 21, 23, 26, 29, 31, 32, 33, 33
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                                                                                                     0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1,
                                0.0, 0.1, 0.0, 0.1, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.1, 0.2, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                                                                                                     0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5,
                                0.0, 0.5, 0.2, 0.5, 0.8, 0.8, 0.8, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.5, 0.8, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.2, 0.0
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                                                                                                     6.3, 6.8, 7.0, 7.2, 7.0, 6.1, 5.4,
                                6.2, 5.0, 4.5, 4.7, 5.0, 5.0, 4.8, 4.9, 5.0, 4.9, 4.2, 4.6, 4.3, 3.7, 3.7, 4.0, 4.5, 5.0, 5.2, 5.6, 5.4, 4.8, 4.0, 4.3,
                                3.5, 2.8, 2.5, 3.6, 3.6, 3.5, 3.5, 3.3, 3.6, 3.5, 3.1, 3.3, 3.9, 4.3, 4.5, 4.7, 4.9
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                                                                                         70, 80, 80, 90, 90, 90, 80,
                                70, 60, 60, 60, 60, 70, 70, 80, 80, 70, 70, 80, 90, 100, 100, 100, 100, 100, 90, 90, 90, 90, 80, 90,
                                80, 70, 80, 60, 70, 70, 80, 80, 80, 90, 90, 100, 90, 110, 140, 150, 160
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                                                                                                                                        1021.5, 1021.0, 1020.7, 1021.0, 1021.3, 1021.6, 1021.7,
                                1021.7, 1021.6, 1021.5, 1021.0, 1020.6, 1020.5, 1020.5, 1020.5, 1020.5, 1020.2, 1020.0, 1019.6, 1019.3, 1019.1, 1018.7, 1018.2, 1018.0, 1017.7, 1017.2, 1016.9, 1017.2, 1017.6, 1017.7, 1017.9,
                                1017.7, 1017.5, 1017.2, 1016.9, 1016.9, 1016.8, 1016.7, 1016.7, 1016.6, 1016.5, 1016.3, 1016.1, 1015.8, 1015.6, 1015.0, 1014.6, 1014.2
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoMontevideo ? new Forecast(
                        new Coordinate( -34.83, -56.17 ), "Montevideo, Uruguay|http://www.yr.no/place/Uruguay/Montevideo/Montevideo~3441575/",
                        new DateTimeOffset( 2013, 07, 20, 18, 0, 0, 0, TimeSpan.FromMinutes( -180 ) ), 3,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                                  8, 8,
                                7, 6, 5, 5, 7, 7, 7, 5,
                                5, 5, 5, 6, 7, 8
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                                              0.1, 0.0,
                                0.0, 0.0, 0.0, 0.1, 0.5, 0.1, 0.7, 0.7,
                                0.0, 0.2, 0.1, 0.5, 0.5, 0.2
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                                              0.5, 0.2,
                                0.2, 0.0, 0.0, 0.5, 0.9, 0.5, 1.0, 1.0,
                                0.2, 0.8, 0.5, 0.9, 0.9, 0.8
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                                              3.1, 3.7,
                                5.0, 4.9, 5.2, 5.1, 7.5, 8.0, 6.9, 7.5,
                                5.8, 6.6, 7.2, 7.5, 8.9, 8.5
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                                              310, 280,
                                230, 240, 260, 270, 270, 280, 290, 260,
                                240, 250, 260, 250, 240, 250
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                                                1009.4, 1010.2,
                                1012.0, 1012.4, 1012.8, 1013.8, 1014.4, 1013.4, 1014.0, 1015.0,
                                1016.2, 1016.9, 1017.0, 1018.6, 1019.1, 1018.0
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoRome ? new Forecast(
                        new Coordinate( 41.89, 12.48 ), "Rome, Italy|http://www.yr.no/place/Italy/Lazio/Rome~3169070/",
                        new DateTimeOffset( 2013, 07, 20, 20, 0, 0, 0, TimeSpan.FromMinutes( 120 ) ), 3,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                                        27, 23,
                                22, 21, 23, 28, 29, 30, 28, 24,
                                22, 20, 23, 29, 32, 32
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                                              0.0, 0.0,
                                0.0, 0.0, 0.0, 0.7, 0.5, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                                              0.0, 0.0,
                                0.2, 0.0, 0.0, 1.0, 0.9, 0.0, 0.0, 0.0,
                                0.0, 0.2, 0.0, 0.0, 0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                                              1.8, 1.4,
                                0.1, 1.2, 1.7, 1.3, 0.7, 2.1, 1.4, 2.0,
                                2.0, 2.0, 2.7, 1.9, 0.4, 3.3
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                                         240, 240,
                                40, 30, 20, 360, 70, 40, 360, 10,
                                20, 20, 10, 30, 20, 240
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                                                1013.7, 1015.0,
                                1014.7, 1014.5, 1015.0, 1014.7, 1015.1, 1014.6, 1014.1, 1015.4,
                                1015.2, 1014.8, 1015.3, 1015.1, 1013.8, 1012.4
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoSydney ? new Forecast(
                        new Coordinate( -33.87, 151.21 ), "Sydney, Australia|http://www.yr.no/place/Australia/Other/Sydney~2147714/",
                        new DateTimeOffset( 2013, 07, 21, 7, 0, 0, 0, TimeSpan.FromMinutes( 600 ) ), 3,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                      9, 11, 14, 15, 12, 10,
                                9, 9, 8, 11, 14, 14, 12, 11,
                                10, 9
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                          0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                          0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                0.0, 0.0
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                          5.7, 7.3, 7.3, 6.5, 5.7, 5.2,
                                4.7, 4.4, 4.5, 5.5, 6.4, 5.4, 4.7, 5.2,
                                5.4, 5.1
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                          300, 300, 290, 290, 300, 310,
                                310, 300, 300, 300, 290, 280, 290, 310,
                                300, 290
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                1015.8, 1016.7, 1014.5, 1013.8, 1016.2, 1017.4,
                                1017.6, 1017.5, 1019.3, 1019.6, 1017.2, 1017.0, 1019.1, 1020.0,
                                1019.5, 1018.6
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoTiverton ? new Forecast(
                        new Coordinate( 41.63, -71.21 ), "Tiverton, US|http://www.yr.no/place/United_States/Rhode_Island/Tiverton~5225245/",
                        new DateTimeOffset( 2015, 02, 27, 19, 0, 0, 0, TimeSpan.FromMinutes( -300 ) ), 6,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                              -8,
                                -10, -12, -4, -5,
                                 -9, -10, -1, -1,
                                  0,   1,  3, -2,
                                 -6,  -9, -3, -4,
                                  0,   4,  6,  5,
                                  6,   4,  1, -1,
                                 -9, -11, -4, -6,
                                 -7,  -5,  1,  1,
                                  0,  -5, -5, -8,
                                -11
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                               0.0,
                                0.0, 0.0, 0.0, 0.0,
                                0.2, 0.2, 0.2, 0.7,
                                0.9, 0.1, 0.0, 0.0,
                                0.0, 0.1, 0.2, 0.7,
                                0.9, 0.7, 0.7, 0.9,
                                0.7, 0.7, 0.7, 0.0,
                                0.0, 0.0, 0.0, 0.0,
                                0.0, 0.2, 0.1, 0.1,
                                0.0, 0.5, 0.0, 0.0,
                                0.1
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                               0.0,
                                0.0, 0.0, 0.0, 0.0,
                                0.8, 0.8, 0.8, 1.0,
                                1.0, 0.5, 0.0, 0.0,
                                0.0, 0.5, 0.8, 1.0,
                                1.0, 1.0, 1.0, 1.0,
                                1.0, 1.0, 1.0, 0.0,
                                0.0, 0.0, 0.0, 0.0,
                                0.2, 0.8, 0.5, 0.5,
                                0.0, 0.9, 0.0, 0.0,
                                0.5
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                               4.7,
                                4.7, 3.9, 1.5, 3.7,
                                3.1, 1.9, 4.7, 4.1,
                                2.8, 4.3, 9.0, 7.0,
                                4.4, 3.7, 2.0, 4.5,
                                4.5, 5.6, 6.2, 5.8,
                                5.5, 3.9, 3.3, 5.7,
                                5.9, 5.0, 3.9, 4.2,
                                4.9, 5.0, 6.0, 5.4,
                                4.9, 7.7, 9.3, 6.4,
                                4.9
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                               310,
                                310, 320, 280, 280,
                                290, 300, 200, 210,
                                210, 250, 300, 300,
                                290, 300, 240, 200,
                                160, 220, 220, 220,
                                230, 310, 230, 300,
                                300, 290, 280, 260,
                                230, 230, 210, 220,
                                240, 320, 330, 330,
                                330
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                        1033.5,
                                1035.6, 1039.7, 1040.0, 1040.6,
                                1040.2, 1039.4, 1035.3, 1029.4,
                                1020.0, 1010.2, 1010.9, 1017.5,
                                1022.7, 1027.2, 1026.3, 1023.2,
                                1015.9, 1005.0, 1000.9, 1000.9,
                                 998.8, 1004.0, 1008.3, 1015.0,
                                1023.9, 1031.0, 1032.1, 1032.4,
                                1029.8, 1026.9, 1020.0, 1013.7,
                                1008.5, 1011.1, 1017.3, 1024.2,
                                1027.2
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoTokyo ? new Forecast(
                        new Coordinate( 35.69, 139.69 ), "Tokyo, Japan|http://www.yr.no/place/Japan/Tokyo/Tokyo~1850147/",
                        new DateTimeOffset( 2013, 07, 21, 6, 0, 0, 0, TimeSpan.FromMinutes( 540 ) ), 3,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                        20, 23, 26, 28, 26, 24,
                                22, 22, 22, 23, 26, 27, 26, 25,
                                24, 24
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                          0.1, 0.1, 0.1, 0.1, 0.2, 0.2,
                                0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2,
                                0.2, 0.2
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                          0.5, 0.5, 0.5, 0.5, 0.8, 0.8,
                                0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.5, 0.8,
                                0.8, 0.8
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                          1.6, 1.5, 1.9, 2.7, 5.2, 4.0,
                                2.8, 2.2, 3.1, 2.9, 2.5, 5.0, 5.4, 2.4,
                                1.1, 0.7
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                           60, 120, 170, 160, 180, 150,
                                110, 100, 100, 110, 160, 180, 180, 160,
                                130, 80
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                1012.4, 1012.3, 1011.1, 1009.9, 1010.5, 1012.0,
                                1011.4, 1010.6, 1011.2, 1011.7, 1010.3, 1008.5, 1007.9, 1008.2,
                                1006.9, 1005.6
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoPositiveOffset ? new Forecast(
                        new Coordinate( 57.05, -135.35 ), "Mount Edgecumbe, US|http://www.yr.no/place/United_States/Alaska/Mount_Edgecumbe~5555851/",
                        new DateTimeOffset( 2014, 03, 08, 13, 0, 0, 0, TimeSpan.FromMinutes( -540 ) ), 6,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                         5,
                                4, 4, 3, 3,
                                2, 2, 1, 5,
                                4, 4, 5, 6,
                                5, 4, 4, 4,
                                4, 0, 1, 3,
                                4, 4, 3, 4,
                                5, 2, 0, 3,
                                3, 4, 4, 3,
                                1, 0, 0, 1,
                                4, 3
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                               0.7,
                                0.9, 0.7, 0.9, 0.7,
                                0.5, 0.7, 0.1, 0.7,
                                0.9, 0.9, 0.9, 0.9,
                                0.7, 0.7, 0.7, 0.5,
                                0.5, 0.2, 0.7, 0.7,
                                0.7, 0.7, 0.7, 0.7,
                                0.7, 0.2, 0.7, 0.9,
                                0.7, 0.7, 0.7, 0.7,
                                0.7, 0.7, 0.7, 0.5,
                                0.2, 0.7
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                               1.0,
                                1.0, 1.0, 1.0, 1.0,
                                0.9, 1.0, 0.5, 1.0,
                                1.0, 1.0, 1.0, 1.0,
                                1.0, 1.0, 1.0, 0.9,
                                0.9, 0.8, 1.0, 1.0,
                                1.0, 1.0, 1.0, 1.0,
                                1.0, 0.8, 1.0, 1.0,
                                1.0, 1.0, 1.0, 1.0,
                                1.0, 1.0, 1.0, 0.9,
                                0.8, 1.0
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                               3.0,
                                3.1, 2.3, 2.5, 1.5,
                                1.7, 1.9, 3.0, 3.0,
                                5.3, 5.5, 3.2, 4.4,
                                3.1, 2.9, 1.9, 1.1,
                                1.3, 2.3, 3.3, 2.9,
                                3.3, 4.0, 4.9, 3.2,
                                2.6, 3.1, 3.8, 6.2,
                                6.0, 3.8, 3.5, 8.6,
                                5.2, 3.9, 2.9, 1.5,
                                1.8, 3.0
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                               130,
                                130, 150, 160, 170,
                                200, 150, 100, 150,
                                120, 120, 110, 170,
                                180, 140, 190, 230,
                                220, 100, 90, 110,
                                120, 110, 100, 110,
                                160, 250, 90, 100,
                                110, 100, 100, 210,
                                260, 240, 130, 130,
                                150, 130
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                                      985.5,
                                984.7, 989.3, 993.7, 1000.0,
                                1004.9, 1010.2, 1013.1, 1014.1,
                                1011.1, 1010.3, 1010.0, 1006.7,
                                1010.2, 1011.8, 1010.7, 1011.1,
                                1015.6, 1018.0, 1016.6, 1012.8,
                                1009.0, 1003.5, 997.8, 997.7,
                                1004.1, 1014.0, 1014.1, 1002.9,
                                995.7, 995.2, 992.5, 1002.3,
                                1021.1, 1025.7, 1026.0, 1024.7,
                                1023.1, 1019.9
                            ) )
                        )
                    ) :
                    file == XmlFile.yrnoNegativeOffset ? new Forecast(
                        new Coordinate( 51.51, -0.13 ), "London, United Kingdom|http://www.yr.no/place/United_Kingdom/England/London~2643743/",
                        new DateTimeOffset( 2014, 03, 30, 0, 0, 0, 0, TimeSpan.FromMinutes( 0 ) ), 6,
                        Dictionary(
                            Pair.Create( ForecastData.Temperature, ReadOnly(
                                8, 7, 15, 18,
                                10, 8, 14, 18,
                                10, 8, 14, 14,
                                9, 9, 19, 15,
                                11, 11, 18, 15,
                                12, 10, 15, 13,
                                11, 7, 13, 12,
                                6, 9, 12, 12,
                                5, 4, 13, 11,
                                5, 4
                            ) ),
                            Pair.Create( ForecastData.PrecipitationPotential, ReadOnly(
                                0.0, 0.0, 0.1, 0.0,
                                0.1, 0.2, 0.1, 0.0,
                                0.7, 0.2, 0.1, 0.2,
                                0.7, 0.2, 0.7, 0.1,
                                0.2, 0.2, 0.2, 0.7,
                                0.2, 0.2, 0.7, 0.7,
                                0.0, 0.2, 0.1, 0.0,
                                0.2, 0.7, 0.7, 0.1,
                                0.2, 0.1, 0.0, 0.0,
                                0.0, 0.2
                            ) ),
                            Pair.Create( ForecastData.SkyCover, ReadOnly(
                                0.2, 0.2, 0.5, 0.2,
                                0.5, 0.8, 0.5, 0.2,
                                1.0, 0.8, 0.5, 0.8,
                                1.0, 0.8, 1.0, 0.5,
                                0.8, 0.8, 0.8, 1.0,
                                0.8, 0.8, 1.0, 1.0,
                                0.2, 0.8, 0.5, 0.0,
                                0.8, 1.0, 1.0, 0.5,
                                0.8, 0.5, 0.0, 0.0,
                                0.0, 0.8
                            ) ),
                            Pair.Create( ForecastData.WindSustainedSpeed, ReadOnly(
                                3.8, 3.1, 2.2, 2.7,
                                3.7, 2.3, 3.7, 4.5,
                                1.0, 2.0, 0.6, 1.7,
                                3.1, 3.1, 3.8, 3.7,
                                3.5, 4.0, 2.8, 1.4,
                                1.6, 0.9, 2.1, 3.2,
                                3.6, 2.8, 3.1, 3.3,
                                2.5, 4.5, 5.0, 3.9,
                                2.4, 1.5, 5.6, 4.7,
                                3.3, 3.3
                            ) ),
                            Pair.Create( ForecastData.WindDirection, ReadOnly(
                                90, 100, 140, 160,
                                80, 80, 90, 190,
                                160, 80, 100, 60,
                                90, 90, 150, 80,
                                80, 80, 180, 160,
                                120, 110, 250, 260,
                                290, 270, 250, 220,
                                200, 180, 180, 260,
                                250, 230, 270, 260,
                                250, 230
                            ) ),
                            Pair.Create( ForecastData.Pressure, ReadOnly(
                                1013.6, 1012.8, 1013.3, 1012.5,
                                1013.3, 1012.4, 1012.3, 1011.1,
                                1012.2, 1011.7, 1011.4, 1008.9,
                                1007.7, 1005.1, 1003.5, 1000.8,
                                999.5, 996.1, 995.9, 996.3,
                                998.1, 999.7, 1002.8, 1006.0,
                                1010.0, 1012.2, 1013.7, 1013.8,
                                1013.7, 1009.9, 1007.4, 1006.8,
                                1009.5, 1009.2, 1010.3, 1013.6,
                                1018.3, 1020.5
                            ) )
                        )
                    ) :
                    null;
            }

            return _xmlFileData[index];
        }

        private static Forecast LoadXmlFile( XmlFile file, Coordinate? fallbackLocation = null ) {
            string resourceName = file.ToString( ) + ".xml";
            return LoadFile( resourceName, fallbackLocation );
        }

        private static Forecast LoadFile( string resourceName, Coordinate? fallbackLocation = null ) {
            using( var source = typeof( TestForecast ).Assembly.GetManifestResourceStream( typeof( TestForecast ), resourceName ) )
                return Forecast.Load( source, fallbackLocation );
        }

        private static ReadOnlyCollection<double> ReadOnly( params double[] values ) {
            return new ReadOnlyCollection<double>( values );
        }

        private static Dictionary<ForecastData, ReadOnlyCollection<double>> Dictionary( params double[] values ) {
            var data = ReadOnly( values );
            return new Dictionary<ForecastData, ReadOnlyCollection<double>> {
                { ForecastData.Temperature, data },
                { ForecastData.PrecipitationPotential, data },
                { ForecastData.SkyCover, data },
                { ForecastData.RelativeHumidity, data }
            };
        }

        private static Dictionary<ForecastData, ReadOnlyCollection<double>> Dictionary( params Pair<ForecastData, ReadOnlyCollection<double>>[] values ) {
            var dictionary = new Dictionary<ForecastData, ReadOnlyCollection<double>>( );
            foreach( var pair in values )
                dictionary.Add( pair.Item1, pair.Item2 );
            return dictionary;
        }


        public enum XmlFile {
            dwml = 0,
            dwmlPreTransition,
            dwmlPostTransition,
            dwmlContainingNil,
            dwmlReordered,
            dwmlNoCloudCover,

            dwmlNoTemperature,
            dwmlNoLocation,

            yrnoEidal,
            yrnoLondon,
            yrnoMontevideo,
            yrnoRome,
            yrnoSydney,
            yrnoTiverton,
            yrnoTokyo,
            yrnoPositiveOffset,
            yrnoNegativeOffset,
        }

        #endregion

    }

}
